package com.twu.biblioteca;


import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class BibliotecaApp {

    //  TODO: Inject another object to display menu, don't println directly into console
    public static void main(String[] args) {
        Biblioteca biblioteca = new Biblioteca();
        Scanner scanner = new Scanner(System.in);
        showWeclomeMessage(biblioteca);
        showMainMenu(biblioteca);
        runOptionById(biblioteca, getUserInput(scanner, "Choose one option by id:"), scanner);

    }

    private static void showWeclomeMessage(Biblioteca biblioteca) {
        System.out.println(biblioteca.getWelcomeMessage());
    }

    private static void showByeByeMessage(Biblioteca biblioteca) {
        System.out.println(biblioteca.getWelcomeMessage());
    }

//    TODO: remove all static methods
    private static void showMainMenu(Biblioteca biblioteca) {
        System.out.println("******MainMenu******");
        for (Option option : getAvailableOptions(biblioteca)){
            System.out.println(option.getDetails());
        }
    }

    private static List<Option> getAvailableOptions(Biblioteca biblioteca){
        List<Option> availableOptions = new ArrayList<Option>();
        for(Option option : biblioteca.getOptions()){
            if(option.isAvailable()){
                availableOptions.add(option);
            }
        }
        return availableOptions;
    }

    private static void runOptionById(Biblioteca biblioteca, int input, Scanner scanner) {
        switch (input){
            case 1: showByeByeMessage(biblioteca); break;
            case 2: runListBooksOption(biblioteca, scanner); break;
            case 3: runReturnBooksOption(biblioteca, scanner); break;
            case 4: runListMoviesOption(biblioteca, scanner); break;
            case 5: runReturnMoviesOption(biblioteca, scanner); break;
            case 6: runUserInfoOption(biblioteca);break;
            default: runInvaildOption(biblioteca, scanner);
        }
    }

    private static void runUserInfoOption(Biblioteca biblioteca) {
        User user = biblioteca.getLoginUser();
        System.out.println("*****UserInfo*****");
        System.out.println("LibraryNumber:" + user.getLibraryNumber());
        System.out.println("Name:" + user.getName());
        System.out.println("EmailAddress:" + user.getEmailAddress());
        System.out.println("PhoneNumber:" + user.getPhoneNumber());
    }

    private static void runInvaildOption(Biblioteca biblioteca, Scanner scanner) {
        System.out.println("Select a valid option! Choose Again!");
        showMainMenu(biblioteca);
        runOptionById(biblioteca, getUserInput(scanner, "Choose one option by id:"),scanner);
    }

    private static void runReturnMoviesOption(Biblioteca biblioteca, Scanner scanner) {
        if(getReturnMovies(biblioteca).isEmpty()){
            System.out.println("List is empty!");
        }
        else {
            showMovies(biblioteca, false);
            returnMovieById(biblioteca, getUserInput(scanner, "Choose one book by id if you want return:"));
        }
        showMainMenu(biblioteca);
        runOptionById(biblioteca, getUserInput(scanner, "Choose one option by id:"), scanner);
    }

    private static void runListMoviesOption(Biblioteca biblioteca, Scanner scanner) {
        if(getAvailableMovies(biblioteca).isEmpty()){
            System.out.println("List is empty!");
        }
        else {
            showMovies(biblioteca, true);
            checkOutMovieById(biblioteca, getUserInput(scanner, "Choose one movie by id if you want check out:"));
        }
        showMainMenu(biblioteca);
        runOptionById(biblioteca, getUserInput(scanner, "Choose one option by id:"), scanner);
    }

    private static void runReturnBooksOption(Biblioteca biblioteca, Scanner scanner) {
        if(getReturnBooks(biblioteca).isEmpty()){
            System.out.println("List is empty!");
        }
        else {
            showBooks(biblioteca, false);
            verifyIdentity(biblioteca, scanner);
            int id =  getUserInput(scanner, "Choose one book by id if you want return:");
            returnBookById(biblioteca, id);
            if(biblioteca.getLoginUser() == null){
                System.out.println("Verify Fails!");
            }
        }
        showMainMenu(biblioteca);
        runOptionById(biblioteca, getUserInput(scanner, "Choose one option by id:"), scanner);
    }

    private static void runListBooksOption(Biblioteca biblioteca, Scanner scanner) {
        if(getAvailableBooks(biblioteca).isEmpty()){
            System.out.println("List is empty!");
        }
        else {
            showBooks(biblioteca, true);
            verifyIdentity(biblioteca, scanner);
            int id = getUserInput(scanner, "Choose one book by id if you want check out:");
            checkOutBookById(biblioteca, id);
            if(biblioteca.getLoginUser() == null){
               System.out.println("Verify Fails!");
            }
        }
        showMainMenu(biblioteca);
        runOptionById(biblioteca, getUserInput(scanner, "Choose one option by id:"), scanner);
    }

    private  static int getUserInput(Scanner scanner,String message){
        System.out.print(message);
        int input =  scanner.nextInt();
        return input;
    }

    private static void showBooksTitle() {
        System.out.println(String.format("|%-4s|%-20s|%-13s|%-13s|", "Id", "Name", "Author", "PublishedYear"));
    }

    private static void showBooks(Biblioteca biblioteca, boolean isAvailable) {
        System.out.println("*****Books*****");
        showBooksTitle();
        List<Book> books = isAvailable? getAvailableBooks(biblioteca) : getReturnBooks(biblioteca);
        for (Book book : books) {
            System.out.println(book.getDetails());
        }
    }

    private static List<Book> getAvailableBooks(Biblioteca biblioteca){
        List<Book> availableBooks = new ArrayList<Book>();
        
        for( Book book: biblioteca.getBooks()){
            if(book.isAvailable()){
                availableBooks.add(book);
            }
        }
        return availableBooks;
    }

    private static List<Book> getReturnBooks(Biblioteca biblioteca){
        List<Book> returnBooks = new ArrayList<Book>();
        for( Book book: biblioteca.getBooks()){
            if(!book.isAvailable()){
                returnBooks.add(book);
            }
        }
        return returnBooks;
    }

    private static void returnBookById(Biblioteca biblioteca, int id) {
        if(biblioteca.getBooks().size()< id || id == 0){
            System.out.println("That book can not be returned.");
        }
        else {
            biblioteca.getBooks().get(id - 1).checkin();
            biblioteca.removeRecord(new Record("Book", biblioteca.getLoginUser().getLibraryNumber(), id));
            System.out.println("Thank you for returning the book.");
        }
    }

    private static void checkOutBookById(Biblioteca biblioteca, int id) {
        if(biblioteca.getBooks().size()< id || id == 0){
            System.out.println("That book is not available.");
        }
        else {
            biblioteca.getBooks().get(id - 1).checkout();
            biblioteca.addRecord(new Record("Book", biblioteca.getLoginUser().getLibraryNumber(), id));
            System.out.println("Thank you! Enjoy the book.");
        }
    }

    private static void verifyIdentity(Biblioteca biblioteca, Scanner scanner) {
        if(biblioteca.getLoginUser() == null) {
            System.out.println("Input your library number and password first!");
            System.out.print("Library number:");
            String libraryNumber = scanner.next();
            System.out.print("Password:");
            String password = scanner.next();
            for (User user : biblioteca.getUsers()) {
                if (user.getLibraryNumber().equals(libraryNumber)
                        && user.getPassword().equals(password)) {
                    biblioteca.getOptions().get(5).setIsAvailable(true);
                    biblioteca.setLoginUser(user);
                }
            }
        }
    }

    private static void showMoviesTitle() {
        System.out.println(String.format("|%-4s|%-20s|%-13s|%-4s|%-6s|", "Id", "Name", "Director", "Year", "Rating"));
    }

    private static void showMovies(Biblioteca biblioteca, boolean isAvailable) {
        System.out.println("*****Movies*****");
        showMoviesTitle();
        List<Movie> movies = isAvailable? getAvailableMovies(biblioteca) : getReturnMovies(biblioteca);
        for (Movie movie : movies) {
            System.out.println(movie.getDetails());
        }
    }

    private static List<Movie> getAvailableMovies(Biblioteca biblioteca) {
        List<Movie> availableMovies = new ArrayList<Movie>();
        for(Movie movie : biblioteca.getMovies()){
            if(movie.isAvailable()){
                availableMovies.add(movie);
            }
        }
        return availableMovies;
    }

    private static List<Movie> getReturnMovies(Biblioteca biblioteca) {
        List<Movie> returnMovies = new ArrayList<Movie>();
        for(Movie movie : biblioteca.getMovies()){
            if(!movie.isAvailable()){
                returnMovies.add(movie);
            }
        }
        return returnMovies;
    }

    private static void returnMovieById(Biblioteca biblioteca, int id) {
        if(biblioteca.getMovies().size()< id || id == 0){
            System.out.println("That movie can not be returned.");
        }
        else {
            biblioteca.getMovies().get(id - 1).checkin();
            System.out.println("Thank you for returning the movie.");
        }
    }

    private static void checkOutMovieById(Biblioteca biblioteca, int id) {
        if(biblioteca.getMovies().size()< id || id == 0){
            System.out.println("That movie is not available.");
        }
        else {
            biblioteca.getMovies().get(id - 1).checkout();
            System.out.println("Thank you! Enjoy the movie.");
        }
    }
}